package io.agora.service

import android.content.Context
import android.util.Log
import io.agora.AgoraAPIOnlySignal
import io.agora.IAgoraAPI
import io.agora.NativeAgoraAPI
import java.util.*
import kotlin.collections.ArrayList

/**
 * Created by XiaoJun on 2017/12/19.
 * version : 1.0.0
 */
class SignalManager {

    private val TAG = SignalManager::class.java.simpleName

    private val appId = "d95f703645f4409ca7c51eadf8968fe8"

    private lateinit var mSignal: AgoraAPIOnlySignal

    private var account: String? = null
    private var channelAttempt: String? = null
    private var currentChannel: String? = null

    fun initialSignal(context: Context) {
        Log.e(TAG, "initial")
        mSignal = AgoraAPIOnlySignal.getInstance(context.applicationContext, appId)
        mSignal.callbackSet(SignalCallBack())
    }

    fun sendMessage(action: String) {
        mSignal.messageChannelSend(currentChannel, action, account)
        Log.e(TAG, "send $action to $currentChannel")
    }

    fun login(userAccount: String) {
        account = userAccount
        mSignal.login2(appId, userAccount, "_no_need_token", 0, "", 30, 5)

        Log.e(TAG, "try to login with $userAccount")
    }

    fun joinChannel(channelName: String) {
        channelAttempt = channelName
        mSignal.channelJoin(channelName)
        Log.e(TAG, "try to join channel $channelName")
    }

    fun leaveChannel(channelName: String) {
        mSignal.channelLeave(channelName)
        Log.e(TAG, "try to level channel $channelName")
    }

    fun logout() {
        mSignal.logout()
        Log.e(TAG, "try to logout")
    }

    private val mCallbacks: MutableList<IAgoraAPI.ICallBack> = ArrayList()

    fun addCallBackListener(listener: IAgoraAPI.ICallBack) {
        if (!mCallbacks.contains(listener)) {
            mCallbacks.add(listener)
        }
    }

    fun removeCallBackListener(listener: IAgoraAPI.ICallBack) {
        mCallbacks.remove(listener)
    }

    /**
     * 信令系统接回调，我们需要做的是新建一个跨进程通信的接口，然后在另外一个地方监听这个
     * 接口的数据变化，然后做出对应的相应
     */
    private inner class SignalCallBack : NativeAgoraAPI.CallBack() {

        override fun onLoginSuccess(uid: Int, fd: Int) {
            Log.e("got", "login success!")

            for (i in mCallbacks) run {
                i.onLoginSuccess(uid, fd)
            }
        }

        override fun onLoginFailed(ecode: Int) {
            Log.e("got", "login failed!")

            for (i in mCallbacks) run {
                i.onLoginFailed(ecode)
            }
        }

        override fun onLogout(ecode: Int) {
            Log.e("got", "logout \$ecode")

            for (i in mCallbacks) run {
                i.onLogout(ecode)
            }
        }

        override fun onLog(txt: String) {

            for (i in mCallbacks) run {
                i.onLog(txt)
            }
        }

        override fun onChannelJoined(chanID: String) {
            currentChannel = channelAttempt
            Log.e(TAG, "Join Success " + chanID)

            for (i in mCallbacks) run {
                i.onChannelJoined(chanID)
            }
        }

        override fun onInviteReceived(channleID: String, account: String, uid: Int, extra: String) {
            mSignal.channelInviteAccept(channleID, account, uid)
            currentChannel = channelAttempt

            for (i in mCallbacks) run {
                i.onInviteReceived(channleID, account, uid, extra)
            }
        }

        override fun onChannelUserJoined(account: String, uid: Int) {
            Log.e("got", "new user!")

            for (i in mCallbacks) run {
                i.onChannelUserJoined(account, uid)
            }
        }

        override fun onChannelJoinFailed(chanID: String, ecode: Int) {
            channelAttempt = null
            currentChannel = null // 加入失败
            Log.e(TAG, "Join Failed" + ecode)

            for (i in mCallbacks) run {
                i.onChannelJoinFailed(chanID, ecode)
            }
        }

        override fun onChannelUserLeaved(account: String, uid: Int) {
            Log.e(TAG, "UserLeaved $account")

            for (i in mCallbacks) run {
                i.onChannelUserLeaved(account, uid)
            }
        }

        override fun onChannelUserList(accounts: Array<String>, uids: IntArray) {
            Log.e("onChannelUserList", Arrays.toString(accounts))

            for (i in mCallbacks) run {
                i.onChannelUserList(accounts, uids)
            }
        }

        override fun onInviteMsg(channelID: String, account: String, uid: Int, msgType: String, msgData: String, extra: String) {
            for (i in mCallbacks) run {
                i.onInviteMsg(channelID, account, uid, msgType, msgData, extra)
            }
        }

        override fun onInviteReceivedByPeer(channleID: String, account: String, uid: Int) {
            for (i in mCallbacks) run {
                i.onInviteReceivedByPeer(channleID, account, uid)
            }
        }

        override fun onInviteEndByPeer(channelID: String, account: String, uid: Int, extra: String) {
            for (i in mCallbacks) run {
                i.onInviteEndByPeer(channelID, account, uid, extra)
            }
        }

        override fun onInviteEndByMyself(channelID: String, account: String, uid: Int) {
            for (i in mCallbacks) run {
                i.onInviteEndByMyself(channelID, account, uid)
            }
        }

        override fun onInviteAcceptedByPeer(channleID: String, account: String, uid: Int, extra: String) {
            for (i in mCallbacks) run {
                i.onInviteAcceptedByPeer(channleID, account, uid, extra)
            }
        }

        override fun onMessageChannelReceive(channelID: String, account: String, uid: Int, msg: String) {
            Log.e("got", msg)

            for (i in mCallbacks) run {
                i.onMessageChannelReceive(channelID, account, uid, msg)
            }
        }

        override fun onMessageInstantReceive(account: String, uid: Int, msg: String) {
            Log.e("got", msg)

            for (i in mCallbacks) run {
                i.onMessageInstantReceive(account, uid, msg)
            }
        }
    }

}